package br.com.foxinline.manager.criar;

import br.com.foxinline.modelo.EntradaSelo;
import br.com.foxinline.modelo.DetalheEntradaSelo;
import br.com.foxinline.modelo.Pessoa;
import br.com.foxinline.modelo.Selo;
import br.com.foxinline.modelo.TipoSelo;
import br.com.foxinline.servico.DetalheEntradaSeloServico;
import br.com.foxinline.servico.EnderecoServico;
import br.com.foxinline.servico.EntradaSeloServico;
import br.com.foxinline.servico.PessoaServico;
import br.com.foxinline.servico.SeloServico;
import br.com.foxinline.servico.TipoSeloServico;
import br.com.foxinline.utilitario.Mensagem;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
/**
 *
 * @author cadomeireles
 */
@ViewScoped
@ManagedBean
public class ManagerCriarEntradaSelo implements Serializable {

    @EJB
    EntradaSeloServico entradaSeloServico;
    @EJB
    PessoaServico pessoaServico;
    @EJB
    EnderecoServico enderecoServico;
    @EJB
    TipoSeloServico tipoSeloServico;
    @EJB
    DetalheEntradaSeloServico detalheEntradaSeloServico;
    @EJB
    SeloServico seloServico;
    
    private EntradaSelo entradaSelo;
    private DetalheEntradaSelo detalheEntradaSelo;
    private List<DetalheEntradaSelo> detalhesEntradaSelo;
    
    private Pessoa fornecedorBuscar;
    private Pessoa fornecedorSelecionado;
    private List<Pessoa> fornecedores;
    
    String editarId;

    @PostConstruct
    public void init() {
        instanciar();
        delegar();
    }

    private void instanciar() {
        this.entradaSelo = new EntradaSelo();
        this.entradaSelo.setFornecedor(new Pessoa());        
        this.detalheEntradaSelo = new DetalheEntradaSelo();
        this.detalhesEntradaSelo = new ArrayList<DetalheEntradaSelo>();
        
        initFornecedor();
    }    
    
    public void initFornecedor() {
        this.fornecedorBuscar = new Pessoa();
        this.fornecedorSelecionado = new Pessoa();
        this.fornecedores = new ArrayList<Pessoa>();
    }
    
    private void delegar() {
        Map<String, String> parametros = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        this.editarId = parametros.get("entradaSeloId");
        
        if (editarId != null) {
            this.entradaSelo = entradaSeloServico.pesquisar(Long.parseLong(editarId));
            this.detalhesEntradaSelo = detalheEntradaSeloServico.pesquisar(this.entradaSelo);
            
            for (DetalheEntradaSelo detalhe : this.detalhesEntradaSelo) {
                detalhe.setSelos(detalheEntradaSeloServico.obterSelos(detalhe));
            }
        }
    }

    public void adicionarDetalheEntradaSelo() {
        this.detalheEntradaSelo.setTipoSelo(tipoSeloServico.pesquisar(this.detalheEntradaSelo.getTipoSelo().getId()));
        
        this.detalhesEntradaSelo.add(this.detalheEntradaSelo);
        this.detalheEntradaSelo = new DetalheEntradaSelo();
    }          
    
    public void editarDetalheEntradaSelo(DetalheEntradaSelo detalhe) {
        this.detalheEntradaSelo = detalhe;
        this.detalhesEntradaSelo.remove(detalhe);
    }
    
    public void removerDetalheEntradaSelo(DetalheEntradaSelo detalhe) {
        Integer quantidadeDistribuida = detalheEntradaSeloServico.quantidadeSelos(detalhe, true);
        
        if (quantidadeDistribuida == 0) {
            this.detalhesEntradaSelo.remove(detalhe);
        } else {
            Mensagem.messagemWarn("Não é possível remover esse entrada. Selos já foram distribuídos.");
        }
        
    }
    
    public void pesquisarFornecedores() {
        this.fornecedores = pessoaServico.pesquisarFornecedor(this.fornecedorBuscar);
    }

    public void selecionarFornecedor() {
        this.entradaSelo.setFornecedor(this.fornecedorSelecionado);
        this.fornecedores = new ArrayList<Pessoa>();
    }    
        
    public void cancelar() {
        initFornecedor();
    }
    
    public List<TipoSelo> autocompletarTipoSelo(String query) {
        return tipoSeloServico.autocompletar(query);
    }
    
    public void limpar() {
        this.detalheEntradaSelo = new DetalheEntradaSelo();
    }

    public void salvar() {
        
        String mensagem;
        
        if (this.entradaSelo.getId() == null) {
            
            // gerar selos
            for (DetalheEntradaSelo detalhe : this.detalhesEntradaSelo) {
                detalhe.setSelos(new ArrayList<Selo>());
                for (int i = detalhe.getNumeroInicial(); i <= detalhe.getNumeroFinal(); i++) {
                    Selo selo = new Selo();

                    selo.setSerie(detalhe.getSerie());
                    selo.setTipoSelo(detalhe.getTipoSelo());
                    selo.setNumero(i);
                    selo.setProtocolado(false);
                    selo.setDistribuido(false);

                    detalhe.getSelos().add(selo);
                }
            }
            
            this.entradaSelo.setDetalhesEntradaSelo(this.detalhesEntradaSelo);            
            entradaSeloServico.salvar(this.entradaSelo);

            instanciar();
            mensagem = "Entrada de Selo cadastrada com sucesso!";

        } else {
            
            // atualiza os selos
            for (DetalheEntradaSelo detalhe : this.detalhesEntradaSelo) {
                
                // detalhe da entrada já existe
                if (detalhe.getId() != null) {

                    Integer quantidadeAtual = detalheEntradaSeloServico.quantidadeSelos(detalhe, false);
                    Integer quantidadeDistribuida = detalheEntradaSeloServico.quantidadeSelos(detalhe, true);                    
                    
                    // se for mesma quantidade: apenas atualizar os valores
                    if (detalhe.getQuantidade() == quantidadeAtual) {
                        detalheEntradaSeloServico.atualizar(detalhe);
                    }

                    // se a nova quantidade for maior que a quantidade no banco: adicionar novos selos
                    else if (detalhe.getQuantidade() > quantidadeAtual) {

                        DetalheEntradaSelo entradaAtual = detalheEntradaSeloServico.pesquisar(detalhe.getId());

                        // adiciona os novos selos a partir do último selo
                        for (int i = entradaAtual.getNumeroFinal() + 1; i <= detalhe.getNumeroFinal(); i++) {
                            Selo selo = new Selo();

                            selo.setSerie(detalhe.getSerie());
                            selo.setTipoSelo(detalhe.getTipoSelo());
                            selo.setNumero(i);
                            selo.setProtocolado(false);
                            selo.setDistribuido(false);

                            detalhe.getSelos().add(selo);
                        }

                        detalheEntradaSeloServico.atualizar(detalhe);
                    }

                    // se a nova quantidade for menor que a quantidade no banco
                    // e maior que a quantidade já distribuída: remover selos
                    else if ((detalhe.getQuantidade() < quantidadeAtual) && (detalhe.getQuantidade() > quantidadeDistribuida)) {

                        List<Selo> ultimosSelos = detalheEntradaSeloServico.ultimasEntradas(detalhe, detalhe.getQuantidade());

                        detalhe.getSelos().removeAll(ultimosSelos);
                        
                        detalheEntradaSeloServico.atualizar(detalhe);

                    // quantidade insuficente para ser removida
                    } else {

                    }

                // novo detalhe da entrada
                } else {

                    // gerar selos
                    detalhe.setSelos(new ArrayList<Selo>());
                    for (int i = detalhe.getNumeroInicial(); i <= detalhe.getNumeroFinal(); i++) {
                        Selo selo = new Selo();

                        selo.setSerie(detalhe.getSerie());
                        selo.setTipoSelo(detalhe.getTipoSelo());
                        selo.setNumero(i);
                        selo.setProtocolado(false);
                        selo.setDistribuido(false);

                        detalhe.getSelos().add(selo);
                    }

                    this.entradaSelo.setDetalhesEntradaSelo(this.detalhesEntradaSelo);
                }

            }
            
            entradaSeloServico.atualizar(this.entradaSelo);

            mensagem = "Entrada de Selo atualizada com sucesso!";
        }

        Mensagem.messagemInfo(mensagem);
    }
    
    public void atualizarValores(String campo) {        
        if (this.detalheEntradaSelo.getNumeroInicial() == null) {
            this.detalheEntradaSelo.setNumeroInicial(this.detalheEntradaSelo.getNumeroFinal() - this.detalheEntradaSelo.getQuantidade());
        }

        if (this.detalheEntradaSelo.getNumeroFinal() == null) {
            this.detalheEntradaSelo.setNumeroFinal((this.detalheEntradaSelo.getQuantidade() + this.detalheEntradaSelo.getNumeroInicial()) - 1);
        }

        if (this.detalheEntradaSelo.getQuantidade() == null) {
            this.detalheEntradaSelo.setQuantidade(this.detalheEntradaSelo.getNumeroFinal() - this.detalheEntradaSelo.getNumeroInicial() + 1);      
        }
    }

    public EntradaSelo getEntradaSelo() {
        return entradaSelo;
    }

    public void setEntradaSelo(EntradaSelo entradaSelo) {
        this.entradaSelo = entradaSelo;
    }

    public DetalheEntradaSelo getDetalheEntradaSelo() {
        return detalheEntradaSelo;
    }

    public void setDetalheEntradaSelo(DetalheEntradaSelo detalheEntradaSelo) {
        this.detalheEntradaSelo = detalheEntradaSelo;
    }

    public List<DetalheEntradaSelo> getDetalhesEntradaSelos() {
        return detalhesEntradaSelo;
    }

    public void setDetalhesEntradaSelos(List<DetalheEntradaSelo> detalhesEntradaSelos) {
        this.detalhesEntradaSelo = detalhesEntradaSelos;
    }

    public Pessoa getFornecedorBuscar() {
        return fornecedorBuscar;
    }

    public void setFornecedorBuscar(Pessoa fornecedorBuscar) {
        this.fornecedorBuscar = fornecedorBuscar;
    }

    public List<Pessoa> getFornecedores() {
        return fornecedores;
    }

    public void setFornecedores(List<Pessoa> fornecedores) {
        this.fornecedores = fornecedores;
    }

    public Pessoa getFornecedorSelecionado() {
        return fornecedorSelecionado;
    }

    public void setFornecedorSelecionado(Pessoa fornecedorSelecionado) {
        this.fornecedorSelecionado = fornecedorSelecionado;
    }

}
